package com.atguigu.spzx.common.log.aspect;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.log.anno.SysLog;
import com.atguigu.spzx.common.log.enu.OperatorType;
import com.atguigu.spzx.common.service.OperLogService;
import com.atguigu.spzx.model.entity.log.SysOperLog;
import com.atguigu.spzx.model.entity.system.AuthContextUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.ServletRequestHandledEvent;

/**
 * @author Mahone
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private OperLogService operLogService;

    @Around("@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, SysLog sysLog) throws Exception {

        SysOperLog sysOperLog = new SysOperLog();

        // 方法执行前，收集参数相关信息
        beforeHandler(sysOperLog,joinPoint,sysLog);


        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
            // 方法执行后 收集响应相关信息
            afterHandler(sysOperLog,proceed,0,null);
        } catch (Throwable e) {
            afterHandler(sysOperLog,proceed,-1,e.getMessage());
            throw  new Exception(e.getMessage());
        }finally {

            operLogService.insertSysOperLog(sysOperLog);
        }


        return proceed;
    }

    private void afterHandler(SysOperLog sysOperLog, Object proceed, int status, String errMessage) {
        if (proceed != null){
            String jsonProceed = JSON.toJSONString(proceed);
            sysOperLog.setJsonResult(jsonProceed);
        }
        sysOperLog.setStatus(status);
        sysOperLog.setErrorMsg(errMessage);
    }

    private void beforeHandler(SysOperLog sysOperLog, ProceedingJoinPoint joinPoint, SysLog sysLog) {

        int type = sysLog.businessType();
        boolean saveRequestData = sysLog.isSaveRequestData();
        OperatorType operatorType = sysLog.operatorType();
        String title = sysLog.title();

        sysOperLog.setBusinessType(type);
        if (saveRequestData){
            // 保存请求参数
            Object[] args = joinPoint.getArgs();
            String jsonString = JSON.toJSONString(args);
            sysOperLog.setRequestMethod(jsonString);

        }
        sysOperLog.setOperName(AuthContextUtil.getUser().getName());
        sysOperLog.setOperatorType(operatorType.name());
        sysOperLog.setTitle(title);

        // http信息
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        sysOperLog.setOperUrl(request.getRequestURI());
        sysOperLog.setRequestMethod(request.getMethod());
        sysOperLog.setOperIp(request.getLocalAddr());

        // 方法反射信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        sysOperLog.setMethod(signature.getMethod().getName());
    }
}
